
#! /usr/bin/python

import sys
import os
import time
sys.path.append('../../../')
from spade import *



class Example(Agent.Agent):
    def _setup(self):
        self.setDefaultBehaviour(self.MainBehav())

    class MainBehav(Behaviour.OneShotBehaviour):
        def _process(self):
            list=self.myAgent.getOrganizationList()
            create=True
            #cheking if the organization already exists
            for o in list:
                if str(o)==str(self.myAgent.orgName):
                    create=False
            o=MyBureaucracy(agent=self.myAgent,nick=self.myAgent.nick,name=self.myAgent.orgName)
            if create:
                self.myAgent.createOrganization(o)
                o.setGoal({"ofrece":"informacion turistica","necesita":"fuentes de informacion turistica"})
                u=Hierarchy(agent=self.myAgent, nick=self.myAgent.nick, name="supervision-1",password="pass",agentList=[])
                o.addUnit(u)
                #adding answering request behaviour
                mens=Behaviour.ACLTemplate()
                mens.setPerformative("request")
                mens.setOntology("Tourism")
                t = Behaviour.MessageTemplate(mens)
                b=self.BrokerBehaviour(u)
                self.myAgent.addBehaviour(b,t)
            else:
                self.myAgent.joinOrganization(o)
                l=o.getUnitList()
                if l==[]:
                    l=o.getUnitList()
                d=o.requestDataForm(l[0])
                if not d:
                    d=o.requestDataForm(l[0])
                d[0]["value"]="supervisor"
                entry=o.requestEntryUnit(l[0],d)
                if not entry:
                    entry=o.requestEntryUnit(l[0],d)
                if entry:
                    u=Hierarchy(agent=self.myAgent,nick=self.myAgent.nick,name=l[0],password=entry)
                    o.joinUnit(u)

        class BrokerBehaviour(Behaviour.Behaviour):
            def __init__(self,u):
                self.unit=u
                Behaviour.Behaviour.__init__(self)

            def _process(self):
                ans=self._receive(True,10)
                if ans:
                    info=self.unit.askMembers(ans.getContent())
                    mens=ACLMessage.ACLMessage()
                    mens.setPerformative("inform")
                    mens.setOntology("Tourism")
                    mens.setSender(self.myAgent.getAID())
                    mens.addReceiver(ans.getSender())
                    mens.setContent(str(info))
                    mens.setConversationId(ans.getConversationId())
                    self.myAgent.send(mens)
                time.sleep(1)



class MyBureaucracy(Bureaucracy.Bureaucracy):
    def onStart(self):
        self.unit=None
    def _process(self):
        time.sleep(2000)


class Hierarchy(Unit.Hierarchy):
    def onStart(self):
        if self.owner==True:
            self.setGoal({"necesita":"fuentes de informacion"})
            self.addDataFormItem(name="rol",desc="rol que asume el agente")
            self.delegate=False
            self.fuentes=[]
            self.supervisores=[]
            self.gotolist=[]
            self.numsupervisores=0
            #max number of subordinated agents
            self.max=4
            #adding the behaviour that addMembers to the unit
            template = Behaviour.ACLTemplate()
            template.setProperty("from",self.name)
            template.setPerformative("inform")
            template.setOntology("spade:x:unit")
            t = Behaviour.MessageTemplate(template)
            self.addMemberBehaviour=self.AddMemberBehaviour(self)
            self.myAgent.addBehaviour(self.addMemberBehaviour, t)

        else:
            d=[{"value":"supervisor","name":"rol"}]
            creation=self.requestCreationPermission(d)
            if creation:
                u=Hierarchy(agent=self.myAgent, nick=self.myAgent.nick, name=self.myAgent.unit,password="pass",agentList=["sitea@apolo.dsic.upv.es"])
                self.addUnit(u)
                mens=Behaviour.ACLTemplate()
                mens.setPerformative("request")
                mens.setOntology("Tourism")
                t = Behaviour.MessageTemplate(mens)
                b=self.BrokerBehaviour(self,u)
                self.myAgent.addBehaviour(b,t)
            else:
                l=self.getUnitList()
                if l==[]:
                    l=self.getUnitList()
                d=self.requestDataForm(l[0])
                if not d:
                    d=self.requestDataForm(l[0])
                d[0]["value"]="supervisor"
                entry=self.requestEntryUnit(l[0],d)
                if not entry:
                    entry=self.requestEntryUnit(l[0],d)
                if entry:
                    u=Hierarchy(agent=self.myAgent,nick=self.myAgent.nick,name=l[0],password=entry)
                    self.joinUnit(u)

    class BrokerBehaviour(Behaviour.Behaviour):
        def __init__(self,currentUnit,unit):
            self.currentUnit=currentUnit
            self.unit=unit
            Behaviour.Behaviour.__init__(self)

        def _process(self):
            ans=self.currentUnit.receiveMessage()
            if ans:
                info=self.unit.askMembers(ans.getContent())
                mens=ACLMessage.ACLMessage()
                mens.setPerformative("inform")
                mens.setOntology("Restaurant")
                mens.setSender(self.myAgent.getAID())
                mens.addReceiver(ans.getSender())
                mens.setContent(str(info))
                mens.setConversationId(ans.getConversationId())
                self.currentUnit.sendPrivateMessage(mens,ans.getSender().getName())
            time.sleep(1)

    def _process(self):
        if self.owner==True:
            if len(self.fuentes)==self.max:
                if not self.delegate:
                    number=str(int(self.name.split("-")[1])+1)
                    agent=self.myAgent.getAID().getName().split("@")[0].split("-")[0]+"-"+number
                    agent=agent+"@"+self.myAgent.getAID().getName().split("@")[1]
                    b = Example(agent,"p")
                    b.orgName="turismo"
                    b.nick=self.nick.split("-")[0]+"-"+number
                    b.unit=self.name.split("-")[0]+"-"+number
                    b.start()
                    self.delegate=True
                else:
                    l=self.getMemberList()
                    u=self.getUnitList()
                    if u==[]:
                        u=self.getUnitList()
                    for m in l:
                        if m not in self.fuentes  and m not in self.supervisores and u!=[] and m not in self.gotolist:
                            self.sendGoto(m,u[0])
                            self.sendAddMember(self.supervisores[0],m,u[0])
                            self.gotolist.append(m)

        time.sleep(1)

    def entryUnitTest(self,sender,desc=None):
      d=desc[0]
      if str(d["name"])=="rol" and str(d["value"])=="fuentes de informacion":
               if sender not in self.fuentes and len(self.fuentes)<self.max:
                   self.fuentes.append(sender)
               return True
      if str(d["name"])=="rol" and str(d["value"])=="supervisor":
               if sender not in self.supervisores:
                   self.supervisores.append(sender)
               return True
      return False

    def creationPermissionTest(self,sender,desc=None):
        d=desc[0]
        if str(d["name"])=="rol" and str(d["value"])=="supervisor" and self.numsupervisores==0:
            self.numsupervisores=self.numsupervisores+1
            self.supervisores.append(sender)
            return True
        return False

    def sendGoto(self,agent,unit):
            mens=ACLMessage.ACLMessage()
            mens.setPerformative("inform")
            mens.setOntology("spade:x:unit")
            mens.setSender(self.myAgent.getAID())
            aid=AID.aid(agent,["xmpp://"+agent])
            mens.addReceiver(aid)
            mens.setContent("Goto:"+unit)
            mens.setProperty("from",self.name)
            cont=0
            while cont<5:
                cont=cont+1
                self.myAgent.send(mens)
                time.sleep(5)

    def sendAddMember(self,manager,member,unit):
            mens=ACLMessage.ACLMessage()
            mens.setPerformative("inform")
            mens.setOntology("spade:x:unit")
            mens.setSender(self.myAgent.getAID())
            aid=AID.aid(manager,["xmpp://"+manager])
            mens.addReceiver(aid)
            mens.setContent("Member:"+member)
            mens.setProperty("from",unit)
            cont=0
            while cont<5:
                cont=cont+1
                self.myAgent.send(mens)
                time.sleep(5)

    class AddMemberBehaviour(Behaviour.Behaviour):
        def __init__(self,unit):
            self.unit=unit
            Behaviour.Behaviour.__init__(self)

        def _process(self):
            m= self._receive(True)
            if m and m.getProperty("from")==self.unit.name:
                if m.getContent().split(":")[0]=="Member":
                    agent=m.getContent().split(":")[1]
                    self.unit.addMember(agent)

    def askMembers(self,about):
        mens=ACLMessage.ACLMessage()
        mens.setPerformative("request")
        mens.setSender(b.getAID())
        mens.setOntology("Restaurant")
        mens.setContent(about)
        mens.setConversationId("id")
        self.sendMessage(mens)
        number=int(self.name.split("-")[1])-1
        espera=(2*self.max)*int(self.niveles()-number)
        #print "Soy "+self.myAgent.getAID().getName()+" y envio a "+str(self.fuentes)+" espero "+str(espera)
        time.sleep(int(espera))
        ans=self.receiveMessage()
        list=[]
        while ans:
            if ans.getPerformative()=="inform":
                if "broker" in ans.getSender().getName():
                    d=eval(ans.getContent())
                else:
                    d={"jid":str(ans.getSender().getName()),"info":eval(ans.getContent())}
                list=list+[d]
            ans=self.receiveMessage()
        #print "Soy "+self.myAgent.getAID().getName()+" y tengo las respuestas "+str(list)
        return list

    def niveles(self):
        cont=0
        name=self.parent.strip(":")[0]
        dad = DF.DfAgentDescription()
        ds = DF.ServiceDescription()
        ds.setType("UNIT")
        dad.addService(ds)
        search = self.myAgent.searchService(dad)
        if search:
          for d in search:
                  for s in d.getServices():
                          prop=s.getProperties()
                          for p in prop:
                              if p["name"].strip("u'")=="parent" and name in p["value"].strip("u'"):
                                  cont=cont+1
        return cont


if __name__ == "__main__":
    agent = "broker-1@apolo.dsic.upv.es"

    b = Example(agent,"pasword")
    b.orgName="turismo"
    b.nick="supervisor-1"
    b.start()





